//+---------------------------------------------------------------------------
//
// Copyright (C) Microsoft Corporation, 2008
//
// File: CommonDataContract.cs
//
// Contents: Shared data contract for the Reputation Web Services
//
// Created by: Andrew Lin (yunlin) July 22nd 2008
//
//----------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Serialization;
using System.Xml;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.IO;

namespace Microsoft.Reputation.Services
{
    public static class StatusCodes
    {
        public const uint OK          = 0x00000000; // everything OK
        public const uint MoreData    = 0x00000001; // there are more pages to fetch in listing API
        public const uint NoMatch     = 0x00001002; // given entry has no match
        public const uint NoUpdate    = 0x00001004; // means object was there, but with earlier stamp
        public const uint RefreshAll  = 0x00001008; // means listing detected deletion and returning all
        public const uint Error       = 0x80000000; // internal error (SQL connection/timeout, out-of-memory, and etc)
        
        //
        // Client ID Token validation
        //
        public const uint TooManyRequests     = 0x80000001; // Number of requests exceeds maximum value in web.config
        public const uint NullClientIdToken   = 0x80000002; // Client ID Token is null
        public const uint NullCustomerGuid    = 0x80000003; // Customer Guid is null
        public const uint NullDeploymentGuid  = 0x80000004; // Deployment Guid is null
        public const uint NullClientGuid      = 0x80000005; // Client ID Token is null
        public const uint NullCustomerVersion = 0x80000006; // Customer version is null or empty

        //
        // Lookup API validation
        //
        public const uint NullLookupRequest               = 0x80000010; // Lookup Request is null or empty
        public const uint NullSearchableMetadata          = 0x80000013; // Null searchable field
        public const uint DuplicateSearchableMetadata     = 0x80000014; // More than one searchable field with same name
        public const uint InvalidSearchableMetadataEncode = 0x80000016; // SearchableFields Metadata is not properly encoded

        //
        // Listing API validation
        //
        public const uint NullListingRequest          = 0x80000020; // Listing Request is null
        public const uint InvalidListingTokenSize     = 0x80000021; // Listing Token size is invalid
        public const uint InvalidListingTokenVersion  = 0x80000022; // Listing Token version is invalid
        public const uint InvalidListingTokenChecksum = 0x80000023; // Listing Token checksum is invalid

        //
        // Filter validation
        //
        public const uint DuplicateRequestedDataType = 0x80000030; // Same Data Type requested more than once in filter
        public const uint ZeroRequestedMetadata      = 0x80000031; // Requested Metadata count is zero
        public const uint MetadataNotRequested       = 0x80000032; // Requested metadata provided, but Metadata Type not requested
        public const uint ZeroRequestedCategory      = 0x80000033; // Requested Category count is zero
        public const uint ReputationNotRequested     = 0x80000034; // Requested Category provided, but Reputation Type not requested

        //
        // Overrides validation
        //
        public const uint InvalidOverrideStamp = 0x80000040; // Client override stamp is less than zero

        //
        // Object Type Specific validation
        //
        public const uint InvalidObjectType = 0x80001001; // Invalidate/none supported object type
        public const uint InvalidDataType   = 0x80001002; // Invalidate requested data type in filter
        public const uint InvalidMetadataType = 0x80001003; // Invalidate requested metadata type in filter
        public const uint InvalidTypeForDataBlock = 0x80001004; // The datablock passed could not be cast into a Byte[]
        public const uint InvalidSearchableMetadata = 0x80001005; // Invalid Searchable Metadata
        public const uint InvalidSearchableMetadataName = 0x80001006; // Invalidate searchable metadata name
        public const uint InconsistentObjectType = 0x80001007; // Object types in requests are not consistent

        //
        // URL Usage Report validation
        //
        public const uint EmptyOverrideExceptionList = 0x80002001;          // Empty Override Exception List
        public const uint InvalidOverrideExceptionUrlOrHostString = 0x80002002; // Invalid Url or Host string in Override Exception
        public const uint InvalidOverrideExceptionCategoryId = 0x80002003;  // Override Exception Category ID is invalid
        public const uint EmptyBlockOverruleList = 0x80002004;              // Empty Block Overrule List
        public const uint InvalidSampleUrlOrHostString = 0x80002005;        // Null or Empty Url string in Sample Urls List
        public const uint InvalidUrlPolicyAction = 0x80002006;              // Url Policy Action is invalid in Block Overrule List
        public const uint EmptySampleUrls = 0x80002007;                     // Empty Sample Url list
        public const uint InvalidSampleUrlCount = 0x80002008;               // Url Sample count is invalid
        public const uint EmptyCategoryPrecedenceCount = 0x80002009;        // Empty Category Precedence Count list
        public const uint InvalidCategoryPrecedenceCountCategoryId = 0x80002010; // Category Precedence Count Category ID is 0
        public const uint EmptyCategoryCountList = 0x80002012;              // Empty Category Count list
        public const uint InvalidCategoryCountCategoryId = 0x80002013;      // Category Query Count Category ID is 0
        public const uint InvalidBlockOverruleCategoryId = 0x80002015;      // Block Overrule List CategoryId is invalid
        public const uint InvalidTimeStamp = 0x80002016;                    // Start time is equal or later than the end time
        public const uint InvalidBlockOverruleUrlOrHostString = 0x80002017; // Invalid Url/Host string in Block Overrule List
        public const uint InvalidSampleRate = 0x80002018;                   // Sample rate is inconsistent in Url usage report
        public const uint ApiDisabled = 0x80002019;                       // The API is not enabled

        public const uint NullUrlTelemetry = 0x80002020;                    // Null Url Telemetry
        public const uint EmptyUrlTelemetry = 0x80002021;                   // Url Telemetry does not contain required data
        public const uint InvalidUrlQueryCount = 0x80002022;                // Total != Unknown + Known

        public const uint BothUrlAndHostStringsInOverrideException = 0x80002023; // Both Url or Host strings exist in Override Exception
        public const uint BothUrlAndHostStringsInSampleUrl = 0x80002024;         // Both Url or Host strings exist in Sample Urls List
        public const uint BothUrlAndHostStringsInBlockOverrule = 0x80002025;     // Both Url or Host strings exist in Block Overrule List
        public const uint NeitherUrlNorHostStringInOverrideException = 0x80002026; // Both Url or Host strings exist in Override Exception
        public const uint NeitherUrlNorHostStringInSampleUrl = 0x80002027;       // Both Url or Host strings exist in Sample Urls List
        public const uint NeitherUrlNorHostStringInBlockOverrule = 0x80002028;   // Both Url or Host strings exist in Block Overrule List

        //
        // URL Error Report validation And LookupCategoriesForUrl
        //
        public const uint EmptyUrlErrorReport = 0x80002030;                 // Null or empty Url error report
        public const uint NullOrEmptyUrlString = 0x80002031;                // Null or empty Url string in Url error report
        public const uint EmptySuggestedCategoryList = 0x80002032;          // Null or empty Suggested Url Category List in Url error report
        public const uint InvalidCategoryRuleId = 0x80002033;               // Url Category Rule Id in Suggested Category List is invalid in Url error report
        public const uint InvalidSiteOwnerInfo = 0x80002034;                // Site owner contact information is missing in Url error report
        public const uint EmptyReportCustomerId = 0x80002035;               // Null or empty Report Customer Id in Url error report
        public const uint InvalidReportFidelity = 0x80002036;               // Report Fidelity is greater than 3 in Url error report
    }

    #region Client Static Data

    [DataContract]
    [Serializable]
    public class ClientIdToken
    {
        [DataMember(IsRequired = true)]
        public Guid CustomerId;
        [DataMember(IsRequired = true)]
        public string CustomerVersion;
        [DataMember(IsRequired = true)]
        public Guid ClientId;
        [DataMember(IsRequired = true)]
        public Guid DeploymentId;

        public ClientIdToken(
            Guid clientId,
            Guid customerId,
            string customerVersion,
            Guid deploymentId)
        {
            this.CustomerId = customerId;
            this.CustomerVersion = customerVersion;
            this.ClientId = clientId;
            this.DeploymentId = deploymentId;
        }

        public static uint IsValidRequest(ClientIdToken clientIdToken)
        {
            if(clientIdToken == null)
            {
                TraceUtility.TraceWarning(
                    Tracing.Source,
                    "Invalid request: provided ClientIdToken is null");
                return StatusCodes.NullClientIdToken;
            }

            if (Guid.Equals(clientIdToken.CustomerId, default(Guid)))
            {
                TraceUtility.TraceWarning(
                    Tracing.Source,
                    "Invalid request: provided ClientIdToken's CustomerId is empty.");
                return StatusCodes.NullCustomerGuid;
            }

            if (Guid.Equals(clientIdToken.DeploymentId, default(Guid)))
            {
                TraceUtility.TraceWarning(
                    Tracing.Source,
                    "Invalid request: provided ClientIdToken's DeploymentId is empty.");
                return StatusCodes.NullDeploymentGuid;
            }

            if (Guid.Equals(clientIdToken.ClientId, default(Guid)))
            {
                TraceUtility.TraceWarning(
                    Tracing.Source,
                    "Invalid request: provided ClientIdToken's ClientId is empty.");
                return StatusCodes.NullClientGuid;
            }

            if (string.IsNullOrEmpty(clientIdToken.CustomerVersion) || string.IsNullOrEmpty(clientIdToken.CustomerVersion.Trim()))
            {
                TraceUtility.TraceWarning(
                    Tracing.Source,
                    "Invalid request: provided ClientIdToken's CustomerVersion is null or empty.");
                return StatusCodes.NullCustomerVersion;
            }

            return StatusCodes.OK;
        }
    }

    #endregion
}
